package util.sign;

import exception.AncException;
import org.apache.commons.lang3.StringUtils;
import util.AncReflectUtil;
import util.sign.annotation.ParticipationSign;
import util.sign.model.GenerateSignStrategy;
import util.sign.model.ParticipationSignElement;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiongyx
 * @date 2020/5/21
 */
public class SignGenerateUtil {

    /**
     * 从对象中获取 参与签名的元素集合
     * @return ParticipationSignElement集合
     * */
    public static List<ParticipationSignElement> getParticipationSignElementList(Object obj) throws Exception{
        Class clazz = obj.getClass();
        // 获得所有非静态的Field
        List<Field> fieldList = AncReflectUtil.getAllNonStaticFields(obj.getClass());

        List<Field> needSignFieldList;
        if(clazz.isAnnotationPresent(ParticipationSign.class)){
            // 类上存在ParticipationSign注解，代表所有属性参与签名
            needSignFieldList = fieldList;
        }else{
            // 类上不存在ParticipationSign注解，选取指定属性参与签名
            needSignFieldList = fieldList.stream()
                // 过滤出有ParticipationSign注解的属性
                .filter(item->item.getAnnotation(ParticipationSign.class) != null)
                .collect(Collectors.toList());
        }

        // 构造ParticipationSignElement列表
        List<ParticipationSignElement> participationSignElements = new ArrayList<>();
        for(Field field : needSignFieldList){
            field.setAccessible(true);
            ParticipationSignElement newElement = ParticipationSignElement.builder()
                .propertyName(field.getName())
                .propertyValue(field.get(obj))
                .build();

            participationSignElements.add(newElement);
        }

        return participationSignElements;
    }

    /**
     * 生成最终用于签名的字符串
     * */
    public static String generateNeedSignStr(Object obj, GenerateSignStrategy generateSignStrategy){
        try {
            List<ParticipationSignElement> participationSignElementList = getParticipationSignElementList(obj);
            return generateNeedSignStr(participationSignElementList,generateSignStrategy);
        } catch (Exception e) {
            throw new AncException("dynamic generateNeedSignStr error",e);
        }
    }

    /**
     * 根据元素集合/策略 生成最终用于签名的字符串
     * */
    public static String generateNeedSignStr(List<ParticipationSignElement> participationSignElementList, GenerateSignStrategy generateSignStrategy){
        if(participationSignElementList.isEmpty()){
            return StringUtils.EMPTY;
        }

        if(generateSignStrategy.getSortKey() != null){
            // 按照指定的方式对参与签名的元素进行排序
            participationSignElementList.sort(generateSignStrategy.getSortKey());
        }

        StringBuilder stringBuilder = new StringBuilder();
        for(ParticipationSignElement item : participationSignElementList){

            String keyName = item.getPropertyName();
            Object value = item.getPropertyValue();
            // k=v的形式生成需要签名的字符串
            stringBuilder.append(keyName).append("=").append(value).append(generateSignStrategy.getItemSeparator());
        }

        // 截取掉最后多余的分隔符
        return stringBuilder.substring(0,stringBuilder.length()-1);
    }
}
